#include "LibDrmInitializer.hpp"
#include <cerrno>
#include <cstdint>
#include <fcntl.h>
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
LibDrmInitializer::LibDrmInitializer(std::string drm_device)
{

    // 1. 打开 DRM 设备
    fd = open(drm_device.c_str(), O_RDWR);
    if (fd < 0)
    {
        perror("Failed to open DRM device");
    }

    // 2. 获取 DRM 资源（显示器、CRTC、连接器等）
    res = drmModeGetResources(fd);
    if (!res)
    {
        perror("Failed to get DRM resources");
    }

    // 3. 找到第一个可用的连接器（显示器）
    int i;
    for (i = 0; i < res->count_connectors; i++)
    {
        conn = drmModeGetConnector(fd, res->connectors[i]);

        if (conn->connection == DRM_MODE_CONNECTED)
        {

            printf("Found connected connector: ID=%d\n", conn->connector_id);

            encoder = drmModeGetEncoder(fd, conn->encoder_id);

            if (encoder)
            {
                printf("Encoder ID=%d, CRTC ID=%d\n", encoder->encoder_id,
                       encoder->crtc_id);

                // 4. 获取当前 CRTC（显示控制器）
                crtc = drmModeGetCrtc(fd, encoder->crtc_id);
                if (crtc)
                {
                    crtcMode = crtc->mode;
                    printf("CRTC ID=%d, width=%d, height=%d crtcMode=%s "
                           "htotal=%d vtotal=%d hdisplay=%d vdisplay=%d\n",
                           crtc->crtc_id, crtc->width, crtc->height,
                           crtcMode.name, crtcMode.htotal, crtcMode.vtotal,
                           crtcMode.hdisplay, crtcMode.vdisplay);

                    break;
                }
                else
                {
                    perror("Failed to get CRTC");
                }

                drmModeFreeEncoder(encoder);
            }
        }

        drmModeFreeConnector(conn);
    }

    if (!crtc)
    {
        fprintf(stderr, "No active connector found!\n");
    }
}

LibDrmInitializer::~LibDrmInitializer()
{
    if (fb_id)
    {
        drmModeRmFB(fd, fb_id);
    }

    if (mapped_dumb && mapped_dumb != MAP_FAILED)
    {
        munmap(mapped_dumb, create_req.size);
    }

    if (crtc)
    {
        drmModeFreeCrtc(crtc);
    }
    if (encoder)
    {
        drmModeFreeEncoder(encoder);
    }
    if (conn)
    {
        drmModeFreeConnector(conn);
    }
    if (res)
    {
        drmModeFreeResources(res);
    }
    if (fd)
    {
        close(fd);
    }
}

int LibDrmInitializer::createFrameBuffer()
{

    // 5. 通过 GEM 分配显存对象，创建一个 dumb buffer（帧缓冲区）
    create_req.width = crtc->width;
    create_req.height = crtc->height;
    create_req.bpp = 32; // 32-bit ARGB

    if (drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_req) < 0)
    {
        perror("Failed to create dumb buffer");

        // goto releaseCrtc;
        return -EINVAL;
    }

    // 6. 映射 dumb buffer 到用户空间(从GPU显存映射到CPU可以访问)
    map_req.handle = create_req.handle;
    if (drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &map_req) < 0)
    {
        perror("Failed to map dumb buffer");
        return -EINVAL;
    }

    mapped_dumb = (uint32_t*)mmap(0, create_req.size, PROT_READ | PROT_WRITE,
                                  MAP_SHARED, fd, map_req.offset);
    if (mapped_dumb == MAP_FAILED)
    {
        perror("Failed to mmap dumb buffer");
        return -EINVAL;
    }

    // 7. 将 GEM 对象转换为 Framebuffer，创建一个 framebuffer 对象
    if (drmModeAddFB(fd, crtc->width, crtc->height, 24, 32, create_req.pitch,
                     create_req.handle, &fb_id) < 0)
    {
        perror("Failed to add framebuffer");
    }

    return fb_id;
}